/*********************************************************************************
Organization 					: 				Georgia Institute of Technology
  
Institute 						:				Cognitive Computing Group(CCL)
 
Authors							: 				Manish Mehta 
 												
Class							:				Trace
 
Function						: 				A class for holding the execution trace
****************************************************************************/
package trace;



import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.List;
import java.util.Vector;

import org.w3c.dom.Node;

import planninglanguage.conditions.Condition;
import planninglanguage.goals.Goal;
import planninglanguage.plans.Plan;
import serialization.BinarySerialization;
import base.WargusGameState;
import behavioradaptation.reasoner.TraceHelpers;

public class Trace implements Serializable{
	public Vector <Entry> trace = new Vector <Entry>();
	public CBRIndexHistory m_cbrindexhistory = new  CBRIndexHistory();
	public Vector <GameStateEntry> gamestates = new Vector <GameStateEntry>();
	private Vector <Integer> indexes = new Vector<Integer>();
	public static enum FailureConditionType {PRECONDITION, ALIVECONDITION, POSTCONDITION, DONTCARE};
	long last_dump;
	public Trace()
	{
		last_dump = 0;
	}
	/*
	 *  Create an entry for the start of a plan 
	 */
	public void createStartEntry(WargusGameState gamestate, Plan p, double starttime, double delay) throws CloneNotSupportedException
	{
		Plan clonedplan = TraceHelpers.cloneEntry(p);		
		Entry curentry = new Entry(gamestate,clonedplan, Entry.EventType.start, starttime, delay, null,FailureConditionType.DONTCARE );
		trace.add(curentry);

	}
	
	
	
	
/*	public void verify(Plan p, String status)
	{
		if(p instanceof BasicOperatorPlan)
		{
			SubGoalPlan sgp = (SubGoalPlan)TraceHelpers.getParentSubGoal(p);
			System.out.println("hello");
			if(!TraceHelpers.isChildofPlan(sgp, p))
			{	
				Reasoner.logger.println("******************************");	
				
				Reasoner.logger.println("Status is: " + status);	
				
				Reasoner.logger.println("Discrepany found :");	
				Reasoner.logger.println("Subgoalplan is: " + sgp);
				Reasoner.logger.println("Plan is: " + sgp.getPlan());
				Reasoner.logger.println("Child is: " + p);		
				Reasoner.logger.println("------------------------------------");	
				
			}
		}	
	}
	*/
	/*
	 * Create an entry for the start of a goal  
	 */
	public void createCBRIndexEntry(String a_goalName, WargusGameState gamestate, Goal a_goal)
	{
		m_cbrindexhistory.add(a_goalName, gamestate, a_goal);		
	}
	
	/*
	 * Get the game state corresponding to when the goal started
	 */
	public WargusGameState getGameStateCBRIndex(String a_goalname)
	{
		return m_cbrindexhistory.getGameState(a_goalname);
	}
	/*
	 * Get the goal class corresponding a goal name entry 
	 */
	public Goal getGoalCBRIndex(String a_goalname)
	{
		return m_cbrindexhistory.getGoal(a_goalname);
	}
	/*
	 * Get the CBR Index entry given a goal name
	 */
	public CBRIndexEntry getCBRIndexEntry(String a_goalname)
	{
		return m_cbrindexhistory.getCBRIndexEntry(a_goalname);
	}
	/*
	 * Right now not being used however the idea is to save the game state 
	 * at every MRE loop
	 */
	public void createGameStateEntry(Node gamestate, double cycle)
	{
	//	gamestates.add(new GameStateEntry(cycle, gamestate));
	}
	/*
	 * Create a Succee Entry for a particular plan 
	 */
	public void createSuccessEntry(WargusGameState gamestate, Plan p, double time) throws CloneNotSupportedException
	{
		Plan clonedplan = TraceHelpers.cloneEntry(p);
		
		Entry curentry = new Entry(gamestate, clonedplan, Entry.EventType.succeed, time, 0.0, null, FailureConditionType.DONTCARE);
		trace.add(curentry);
	}
	/*
	 * Create a Failure Entry for the plan 
	 */
	public void createFailureEntry(WargusGameState gamestate, Plan p, double time, List <Condition> condlist, FailureConditionType c) throws CloneNotSupportedException
	{
		Plan clonedplan = TraceHelpers.cloneEntry(p);
		Entry curentry = new Entry(gamestate, clonedplan, Entry.EventType.fail, time, 0.0, condlist, c);
		trace.add(curentry);
	}
	/*
	 * Simple Helper Function for getter and setter
	 */
	public int size()
	{
		return trace.size();		
	}
	public int getSize()
	{
		return trace.size();		
	}
	public Vector <Entry> getTrace()
	{
		return trace;		
	}
	public Entry get(int i)
	{
		return (Entry)trace.get(i);		
	}
	public Entry getValue(int i)
	{
		return (Entry)trace.get(i);		
	}
	public void setSize(int size)
	{
		trace.setSize(size);		
	}
	public void setTrace(Vector <Entry> v)
	{
		trace = v;		
	}
	public void set(int i, Entry e)
	{
		trace.setElementAt(e, i);		
	}
	public void setValue(int i, Entry e)
	{
		trace.setElementAt(e, i);		
	}
	/*
	 * Dump the execution trace into a serialized version 
	 * that can then be loaded later on for debugging and testing 
	 * purposes and running the behavior adaptation subsystem
	 */
	public void dump()
	{
		if(System.currentTimeMillis() - last_dump > 10000)
		{
			last_dump = System.currentTimeMillis(); 	
			BinarySerialization.dump(this, "game-trace.dat");	
			// printTrace();
		}	
	}
	/*
	 * Helper Function to load the trace in order to debug and 
	 * do a sample run of the behavior adaptation subsystem
	 */
	public void load()
	{
		Trace tr = (Trace)BinarySerialization.load("game-trace.dat");
		tr.printTrace();
	}
	public void printTrace()
	{
		try {
			   FileWriter outFile = new FileWriter("game-trace.txt");
			   PrintWriter out = new PrintWriter(outFile);
			   for(int i = 0; i < trace.size(); i++)
				{
					Entry e = (Entry)trace.get(i);
					System.out.println("Trace Entry is:");
					System.out.println("Behavior Status is:" + e.getEventType());
					System.out.println("Behavior Delay is:" + e.getDelay());
					System.out.println("Behavior Time is:" + e.getTime());
					System.out.println("Plan is:" + e.getPlan());
					out.println("Behavior Status is:" + e.getEventType());
					out.println("Behavior Delay is:" + e.getDelay());
					out.println("Behavior Time is:" + e.getTime());
					out.println("Plan is:" + e.getPlan());
				
				}
			   out.flush();
			   out.close();
		}
		catch (IOException e){
			  e.printStackTrace();}    				
	}
	

	
}
